<template>
  <div v-show="!hidden" class="el-form-item asterisk-left el-form-item--label-right" style="">
    <label :for="id" class="el-form-item__label" :style="leftWidth">{{ label || name }}</label>
    <div class="el-form-item__content">
      <slot :input="input"></slot>
      <div class="clearfix"></div>
      <div v-show="isNotValid" class="text-warning">{{ message }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import {inject, ref, watch, computed , onMounted } from 'vue';
import Asserts from "@/lang/core/asserts";
import Layers from "@/lang/layers/index";

/**
 * FormLayout
 *
 * 业务上，包含： “页面布局” 和 “数据有效性检验” 两个关键功能；
 * 界面上，包含每一个 form-item 的具体绘制方式。
 */
const props = defineProps({
    // 字段名，允许多个组件合并，放到同一个布局单元中
    name: {type: String}
    // 中文名，未定义则使用字段名
    , label: {type: String, default: undefined}
    // 是否隐藏
    , hidden: {type: Boolean, default: false}
    // 是否必填
    , require: {type: Boolean, default: false}
    // 数据验证规则
    , rules: {type: Array, default: undefined}
    // 整个组件占用的栈格大小
    , span: {type: Number, default: 24}
    // 布局参数：标签宽度
    , labelWidth: {type: [Number, String], default: undefined}
    // // 布局风格
    // , theme: {type: String, default: 'default'}
    // 布局参数：栈格分布
    // , col: {type: Array, default: () => [8, 16]}
});

/**
 * 组件使用的对象模型
 *
 * @type {FastForm}
 */
const fast_form = inject('fast_form');

/**
 * 组件使用的对象模型
 *
 * @type {FormInput}
 */
let input = fast_form.getFormInput(props.name);
Asserts.notBlank(input, 'form input is undefined:' + props.name);

// 初始化：记录所有通过 props 属性，这些数值主要是用于输入校验
{
    // input.name = props.name;
    // input.col = props.col;
    input.span = props.span;
    input.label = props.label;
    input.rules = props.rules;
    input.hidden = props.hidden;
    input.require = props.require;
}

// 组件 ID
const id = ref(input.id);

// 参数校验：是否有效
const valid = ref<boolean | undefined>(undefined);
// 参数校验：异常信息
const message = ref<string>('');

// 左布局宽度
const leftWidth = ref<string>('width: 100px;');
// 右布局宽度
const rightWidth = ref<string>('margin-left: 100px;');

// 无效输入
const isNotValid = computed(()=>{
    return valid.value === false;
});

// 监听 props 变化
watch(() => props.hidden, (val) => {
    input.hidden = val;
});

watch(() => props.require, (val) => {
    input.require = val;
});

// 组件挂载时初始化
onMounted(() => {
    if (input.theme === 'inline') {
        // 水平布局
        leftWidth.value = '';
        rightWidth.value = '';
    } else if (Layers.isNotBlank(props.labelWidth)) {
        // 竖向布局
        leftWidth.value = 'width: ' + props.labelWidth + 'px;';
        rightWidth.value = 'margin-left: ' + props.labelWidth + 'px;';
    }
});

/**
 * 启动数据校验
 *
 * 首次校验是特殊的，需要通知到当前组件，触发界面变化
 */
function onStartupValidator() {
    valid.value = input.valid;
    message.value = input.message;
}

/**
 * 数据受控函数
 *
 * 数据发生变化的时候，会通知到当前组件，由当前组件触发校验函数
 *
 * @see FormInput
 * @param val
 */
function onChangeValue(val: any) {
    input.checkValidity();
    valid.value = input.valid;
    message.value = input.message;
}

// 注册布局侦听
input.setLayout({onChangeValue, onStartupValidator});
</script>

<style scoped>
</style>